package com.dy.controller;

import com.dy.entity.Sale;
import com.dy.service.IFeignSellService;
import com.dy.util.ToolUtil;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * @Auther: dy
 * @Date: 2022/4/24 - 04 - 24 - 19:07
 * @Description: com.dy.controller
 * @version: 1.0
 */
@RestController
@RequestMapping("/redis")
public class TestRedis {
    @Qualifier("com.dy.service.IFeignSellService")
    @Autowired
    private IFeignSellService feignSellService;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private RLock rLock;

    @GetMapping("/testRedis/{serial}")
    public Object testRedis(@PathVariable("serial")String serial) throws InterruptedException {
        if (ToolUtil.bloomFilter.mightContain(serial)){
            return cache(serial);
        }
        return null;
    }
    //防止缓存击穿
    public Object cache(String serial) throws InterruptedException {
        String key = serial;
        if (!redisTemplate.hasKey(serial)){
            boolean lock = rLock.tryLock(0,10,TimeUnit.SECONDS);
            if (lock){
                Sale sale = feignSellService.selectSaleBySerial(serial);
                if (sale != null){
                    //防止服务雪崩
                    Long minTime = ToolUtil.REDIS_MIN_TIME;
                    Long time = (System.currentTimeMillis()+serial.hashCode())%120;
                    if (time < minTime){
                        time = minTime;
                    }
                    redisTemplate.opsForValue().set(serial,sale,time, TimeUnit.SECONDS);
                }
            }else{
                Thread.sleep(500);
            }
        }
        return redisTemplate.opsForValue().get(serial);
    }
}
